using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Utils.Coroutine
{
    /// <summary>
    /// 用于管理动作队列的类，支持添加等待和回调，并按顺序执行。
    /// </summary>
    public class ActionQueue
    {
        // 这里使用Queue来储存ActionEntry
        private readonly Queue<ActionEntry> _actions;

        // 记录开启的协程，便于停止
        private UnityEngine.Coroutine _coroutine;

        // 记录是否完成
        /// <summary>
        /// 获取队列是否执行完毕。
        /// </summary>
        public bool IsComplete { get; private set; }

        private readonly MonoManager _monoManager;

        /// <summary>
        /// 私有构造函数，使用工厂模式创建实例。
        /// </summary>
        public ActionQueue()
        {
            _actions = new Queue<ActionEntry>();
            _monoManager = MonoManager.Current;
        }
        
        /// <summary>
        /// 创建一个新的ActionQueue实例，并添加一个等待到动作队列。
        /// </summary>
        /// <param name="actions"> 要等待的动作队列。</param>
        /// <returns></returns>
        public static ActionQueue WhenAll(params ActionQueue[] actions)
        {
            ActionQueue queue = new ActionQueue();
            queue.AppendWaitUntil(() => actions.All(a => a.IsComplete));
            return queue;
        }

        /// <summary>
        /// 添加一个等待到动作队列，便于链式编程。
        /// </summary>
        /// <param name="enumerator">要等待的IEnumerator。</param>
        /// <returns>当前ActionQueue实例。</returns>
        public ActionQueue Append(IEnumerator enumerator)
        {
            _actions.Enqueue(new ActionEntry(enumerator));
            return this;
        }

        /// <summary>
        /// 添加一个回调到动作队列，便于链式编程。
        /// </summary>
        /// <param name="callback">要执行的Action回调。</param>
        /// <returns>当前ActionQueue实例。</returns>
        public ActionQueue Append(Action callback)
        {
            _actions.Enqueue(new ActionEntry(callback));
            return this;
        }

        /// <summary>
        /// 添加一个等待和一个回调到动作队列，便于链式编程。
        /// </summary>
        /// <param name="enumerator">要等待的IEnumerator。</param>
        /// <param name="callback">要执行的Action回调。</param>
        /// <returns>当前ActionQueue实例。</returns>
        public ActionQueue Append(IEnumerator enumerator, Action callback)
        {
            _actions.Enqueue(new ActionEntry(enumerator, callback));
            return this;
        }

        /// <summary>
        /// 启动动作队列的执行。
        /// </summary>
        public ActionQueue Run()
        {
            _coroutine = _monoManager.StartCoroutine(RunCoroutine());
            return this;
        }

        /// <summary>
        /// 停止当前正在执行的动作队列。
        /// </summary>
        public void Cancel()
        {
            if (_monoManager != null && _coroutine != null)
                _monoManager.StopCoroutine(_coroutine);
        }

        /// <summary>
        /// 运行动作队列中的操作。
        /// </summary>
        /// <returns>IEnumerator用于协程调度。</returns>
        private IEnumerator RunCoroutine()
        {
            IsComplete = false;
            while (_actions.Count > 0)
            {
                ActionEntry entry = _actions.Dequeue();
                if (entry.Enumerator != null)
                    yield return entry.Enumerator;
                entry.Callback?.Invoke();
            }

            IsComplete = true;
        }
    }
}